package org.testis.testdriver.operations;

import org.testis.testdriver.exceptions.InvalidTestPartDecorationException;
import org.testis.testdriver.AtofEnumaration;
import org.testis.testdriver.TestPart;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


/**
 * Context class used to build the and link the TestPart Operation decorators.
 * 
 * @author barisergun
 */
public class TestPartOperationContext
{

    private TestPartOperations[] partOperations = null;


    /**
     * This constrcutor is used to automatically construct Operation Classes related 
     * to the TestPart given as parameter. Every TestPart object holds information 
     * about its Decorator Oeprations according to this information Decorator
     * Classes are constructed with reflection and linked to each other.
     * 
     * @param testPartToRun TestPart that is in charge.
     */
    public TestPartOperationContext(TestPart testPartToRun)
    {
        Exception exception = null;
        try {

            String[] operations = testPartToRun.getRunOperations();

            partOperations = new TestPartOperations[operations.length + 1];

            partOperations[0] = new TestPartRootOperation(testPartToRun);

            for (int x = 0; x < operations.length; x++) {
                Class<?> cls = Class.forName("org.testis.testdriver.operations." +
                                             operations[x]);
                Constructor[] constr = cls.getDeclaredConstructors();
                Object[] params = new Object[]{testPartToRun};
                for (int i = 0; i < constr.length; i++) {
                    Class[] constParams = constr[i].getParameterTypes();
                    if (constParams.length == 1) {
                        partOperations[x + 1] = (TestPartOperationDecorator) constr[i].newInstance(
                            params);

                    }
                }

            }

            for (int y = 0; y < partOperations.length - 1; y++) {
                ((TestPartOperationDecorator) partOperations[y + 1]).
                    setDecorator(partOperations[y]);
            }



        } catch (InstantiationException ex) {
            exception = ex;
        } catch (IllegalAccessException ex) {
            exception = ex;
        } catch (IllegalArgumentException ex) {
            exception = ex;
        } catch (ClassNotFoundException ex) {
            exception = ex;
        } catch (InvocationTargetException ex) {
            exception = ex;
        } finally {
            if (exception != null) {
                throw new InvalidTestPartDecorationException(
                    exception.toString());
            }
        }

    }


    /**
     * This method is used to run the Decorator Operations starting from the 
     * last linked Decorator
     * 
     * @param mode Execution Debugging Mode 
     */
    public boolean runContext(AtofEnumaration.DebuggingMode mode) throws
        InterruptedException
    {
        return partOperations[partOperations.length - 1].runOperation(mode);
    }
}
